/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package domain;
import domain.exceptions.*;
//import domain.exceptions.CannotPlaceAgentHereException;
import domain.Game.action;
//import domain.exceptions.CannotFlagWallSquareException;
/**
 *
 * @author shaigi
 */
public abstract class Square {
    
    private int     _row;
    private int     _column;
    private Agent   _agent;
    private Flag    _flag;
    
    //private Vector<Observer> _observers = new Vector<Observer>();
    
    @Override
    public abstract String toString();
    public abstract void placeAgent(Agent agent) throws CannotPlaceAgentHereException;
    
    public boolean isThereAgentHere(){
        return _agent != null && !_agent.isDead();
    }
    
    public Square neighbour(action d, Board b) throws NoSuchSquareException{
        Square res = null;
        //Board b = Game._board;
        try{
        	System.out.println("act: "+d);
            switch (d){
                case UP:    res = b.getSquare(_row-1, _column);   break;
                case DOWN:  res = b.getSquare(_row+1, _column);   break;
                case RIGHT: res = b.getSquare(_row, _column+1);   break;
                case LEFT:  res = b.getSquare(_row, _column-1);   break;
            }
        } catch (IndexOutOfBoundsException e){
            throw new NoSuchSquareException();
        }
        if (res == null)	// In case of action is "shoot",
        	return this;	// agent will remain in his square.
        return res;
    }
    
//    public Square neighbourAStar(direction d, Board board) throws NoSuchSquareException{
//        Square res = null;
//        Board b = board;
//        try{
//            switch (d){
//                case UP:    res = b.getSquare(_row-1, _column);   break;
//                case DOWN:  res = b.getSquare(_row+1, _column);   break;
//                case RIGHT: res = b.getSquare(_row, _column+1);   break;
//                case LEFT:  res = b.getSquare(_row, _column-1);   break;
//            }
//        } catch (IndexOutOfBoundsException e){
//            throw new NoSuchSquareException();
//        }
//        return res;
//    }
    
    public void removeAgent() throws Exception {
        if (this._agent == null) {
            throw new Exception("Trying to remove an Agent from an empty square");
        } else {
            this._agent = null;
            //TODO update GUI
        }
    }
    
    public Agent getAgent() {
        return _agent;
    }
    
    public int getRow() {
        return _row;
    }

    public void setRow(int row) {
        this._row = row;
    }

    public int getColumn() {
        return _column;
    }

    public void setColumn(int column) {
        this._column = column;
    }

    public void setAgent(Agent agent) {
        this._agent = agent;
        //TODO update GUI
    }
    
    public String toStringLocation(){
        return _row + "," + _column;
    }

    public boolean isContainFlag() {
        return _flag != null;
    }

    public void removeFlag(){
    	this._flag = null;
    }
    
    public void setFlag(Flag flag) throws CannotFlagSquareException {
        if ( !isContainFlag() ){
            this._flag = flag;
            //TODO update GUI:
            //updateGui();
        }
        else{
            throw new CannotFlagSquareException("This square is already flaged");
        }
    }
//    
//    int getCost() {
//        return this._flag.getValue();
//    }
    
    public boolean equals(Square other){
    	if (!(other instanceof Square)){
			return false;
		}
    	Square otherSquare = (Square) other;    	
        return this._row == otherSquare._row  &&
               this._column == otherSquare._column &&
               //this.getAgent().equals(otherSquare.getAgent()) &&
               this.isContainFlag() == otherSquare.isContainFlag();
               
    }

    public Flag getFlag() {
        return _flag;
    }
    
    public int convertToLocation(int columnSizeOfBoard){
    	return this._column+columnSizeOfBoard*this._row;
    }
    /*
    public void subscribe(Observer observer){
        this._observers.addElement(observer);
    }

    private void updateGui() {
        for (Iterator<Observer> it = _observers.iterator(); it.hasNext();) {
            Observer observer = it.next();
            observer.updateGui(this);
        }
    }
     */
}
